package acn.spring.domain;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.validation.constraints.DecimalMin;
import javax.validation.constraints.NotNull;

import org.joda.time.DateTime;
import org.springframework.data.jpa.domain.AbstractPersistable;

@Entity
@Table(name = "ORDERR")
public class Order extends AbstractPersistable<Long> {

	/**
	 * 
	 */
	private static final long serialVersionUID = 3788923713157633276L;

	@NotNull
	@ManyToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE })
	private Customer customer;

	@DecimalMin(value = "0", inclusive = false)
	private BigDecimal price;

	@OneToMany(mappedBy = "pk.order", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
	private Set<ProductOrder> products = new HashSet<ProductOrder>();

	@NotNull
	@Enumerated(EnumType.STRING)
	private OrderStatus status;

	@NotNull
	@Column(name = "orderDate")
	private Date date;

	public Order() {
		this.price = new BigDecimal(0);
		this.date = DateTime.now().toDate();
		this.status = OrderStatus.IN_PROGRESS;
	}

	public Customer getCustomer() {
		return customer;
	}

	public void setCustomer(Customer customer) {
		this.customer = customer;
	}

	public BigDecimal getPrice() {
		return price;
	}

	public void setPrice(BigDecimal price) {
		this.price = price;
	}

	public Set<ProductOrder> getProductOrders() {
		return products;
	}

	public void setProductOrders(Set<ProductOrder> productOrders) {
		this.products = productOrders;
	}

	public void removeAllProducts() {
		products.clear();
		setPrice(new BigDecimal(0));
	}

	public void removeProduct(Product product) {

		for (ProductOrder productOrder : products) {
			if (productOrder.getProduct().equals(product)) {
				products.remove(productOrder);
				setPrice(getPrice().subtract(product.getPrice().multiply(new BigDecimal(productOrder.getQuantity()))));
				break;
			}
		}
	}

	public void updateProduct(Product product, int quantityNew) {
		int quantityOld = 0;

		for (ProductOrder productOrder : products) {
			if (productOrder.getProduct().equals(product)) {
				quantityOld = productOrder.getQuantity();
				productOrder.setQuantity(quantityNew);
				break;
			}
		}

		if (quantityOld == 0) {
			ProductOrder productOrderNew = new ProductOrder(this, product, quantityNew);
			products.add(productOrderNew);
		}

		BigDecimal oldPrice = product.getPrice().multiply(new BigDecimal(quantityOld));
		BigDecimal newPrice = product.getPrice().multiply(new BigDecimal(quantityNew));

		setPrice(getPrice().subtract(oldPrice).add(newPrice));
	}

	public void addProduct(Product product, int quantityAdditional) {
		int quantityOld = 0;

		for (ProductOrder productOrder : products) {
			if (productOrder.getProduct().equals(product)) {
				quantityOld = productOrder.getQuantity();
				productOrder.setQuantity(quantityOld + quantityAdditional);
				break;
			}
		}

		if (quantityOld == 0) {
			ProductOrder productOrder = new ProductOrder(this, product, quantityAdditional);
			products.add(productOrder);
		}

		setPrice(price.add(product.getPrice().multiply(new BigDecimal(quantityAdditional))));
	}

	public void addProduct(Product product) {
		addProduct(product, 1);
	}

	public void removeProductOrder(ProductOrder productOrder) {
		products.remove(productOrder);
	}

	public OrderStatus getStatus() {
		return status;
	}

	public void setStatus(OrderStatus status) {
		this.status = status;
	}

	public Date getDate() {
		return date;
	}

	public void setDate(Date date) {
		this.date = date;
	}

	public int getProductSize() {
		return products.size();
	}

}
